/***************************************************************************************************
*Copyright(C),2010-2016,Sumscope
*FileName	:  WideString.cpp
*Author	:  scofined.qi
*Version	:  1.0
*Date		:  2016/01/12
*Desc		:  //用于主要说明此程序文件完成的主要功能
*Relation :  
*Others	:  //其他内容说明
*Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
*History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
***************************************************************************************************/

#include "WideString.h"
#include "BaseString.h"
#include <stdarg.h>

namespace qb{
	namespace base{

		static char inline GetCaseChar(bool igoreCase,const char& c)
		{
			return (!igoreCase && (c>='A' && c<='Z'))?c+32:c;
		}

		WideString::WideString():m_string(0),m_size(0),m_capcity(INIT_CAPCITY)
		{
			reset();
		}

		WideString::WideString( const Element* str ):m_string(0),m_size(0),m_capcity(INIT_CAPCITY)
		{
			reset();
			append(str);
		}

		WideString::WideString( const Element* str,int len ):m_string(0),m_size(0),m_capcity(INIT_CAPCITY)
		{
			reset();
			append(str,len);
		}

		WideString::WideString(const WideString& bs):m_string(0),m_size(0),m_capcity(INIT_CAPCITY)
		{
			reset();
			append(bs);
		}

		WideString::~WideString()
		{
			reset();
		}
		WideString& WideString::Format(const wchar_t* format,...)
		{
			va_list args;
			int ret;  
			va_start (args, format);
			const int bufsize = 1024;
			wchar_t buf[bufsize] = {0};
			memset(buf,0,bufsize*sizeof(wchar_t));
			ret = vswprintf(buf,bufsize-1, format, args);
			va_end (args);
			clear();
			append(buf,ret);
			return *this;
		}
		void WideString::expand( int size )
		{
			// 额外增加的1个字节使得用于字符串0强行结尾
			if(m_string && size<=m_capcity)
				return;
			int capcity = m_capcity+m_capcity/2;
			capcity = capcity<INIT_CAPCITY?INIT_CAPCITY:capcity;
			capcity = capcity<size?size:capcity;
			capcity = (capcity/4+1)*4-1;
			int bytes   = sizeof(Element)*(capcity+1);
			Element* arr = new (std::nothrow) Element[capcity+1];
			memset(arr,0,bytes);
			if(m_size>0)
			{
				memcpy(arr,m_string,m_size*sizeof(Element));
			}
			if(m_string)
				delete [] m_string;
			m_string  = arr;
			m_capcity = capcity;
		}

		WideString::ThisType& WideString::operator=( Element c )
		{
			return assign(c);
		}

		WideString::ThisType& WideString::operator=( const WideString& bs )
		{
			return assign(bs);
		}

		WideString::ThisType& WideString::operator=( const Element* str )
		{
			return assign(str);
		}

		void WideString::clear()
		{
			m_size=0;
			Element e={0};
			if(m_string)
				m_string[0]=0;
		}

		void WideString::reset()
		{
			if(m_string)
				delete [] m_string;
			m_string = 0;
			m_size = 0;
			m_capcity = INIT_CAPCITY;
			m_null[0] = 0;
			m_null[1] = 0;
		}

		WideString::ThisType& WideString::assign( Element c )
		{
			return assign(&c,1);
		}

		WideString::ThisType& WideString::assign( const Element* str )
		{
			return assign(str,str?length(str):0);
		}

		WideString::ThisType& WideString::assign( const Element* str,int len )
		{
			clear();
			return append(str,len);
		}

		WideString::ThisType& WideString::assign( const WideString::ThisType& br )
		{
			clear();
			append(br.m_string,br.m_size);
			return *this;
		}

		WideString::ThisType& WideString::append(int count,Element c )
		{
			if(count>0)
			{
				expand(size()+count);
				for (int i=0;i<count;i++)
				{
					append(c);
				}
			}
			return *this;
		}
		WideString::ThisType& WideString::append( Element c )
		{
			return append(&c,1);
		}

		WideString::ThisType& WideString::append( const Element* str )
		{
			return append(str,str?length(str):0);
		}

		WideString::ThisType& WideString::append( const Element* str,int len )
		{
			if(str && len>0)
			{
				if(!m_string || m_size+len>m_capcity)
					expand(m_size+len);
				memcpy(m_string+m_size,str,sizeof(Element)*len);
				m_size += len;
				m_string[m_size]=0;
			}
			return *this;
		}

		WideString::ThisType& WideString::append( const WideString::ThisType& br )
		{
			return append(br.m_string,br.m_size);
		}

		WideString::ThisType& WideString::push_back( Element c )
		{
			return append(c);
		}

		WideString::ThisType& WideString::push_back( const Element* str )
		{
			return append(str);
		}

		WideString::ThisType& WideString::push_back( const Element* str,int len )
		{
			return append(str,len);
		}

		WideString::ThisType& WideString::push_back( const WideString::ThisType& br )
		{
			return append(br);
		}

		WideString::ThisType& WideString::insert( int pos,const Element* str,int len )
		{
			if(str && len>0)
			{
				pos = (pos<0||pos>=m_size)?m_size:pos;
				if(!m_string || m_size<=0)
				{
					append(str,len);
				}else if(m_size+len<=m_capcity)
				{
					for (int i=m_size+len-1;i>=pos+len;i--){m_string[i]=m_string[i-len];}
					for (int i=0;i<len;i++){m_string[i+pos]=str[i];}
					m_size += len;
				}else{
					ThisType temp;
					temp.expand(m_size+len);
					temp.append(m_string,pos);
					temp.append(str,len);
					temp.append(m_string,m_size-pos);
					swap(temp);
				}
			}
			return *this;
		}

		WideString::ThisType& WideString::erase( int pos,int len/*=1*/ )
		{
			if(m_string && m_size>0 && pos>=0 && pos<m_size && len>0)
			{
				for (int i=pos;i<m_size;i++)
				{
					m_string[i]=(i+len>=m_size)?0:m_string[i+len];
				}
				if (pos < m_size)
				{
					int left = m_size - pos;
					m_size -= len < left ? len : left;
				}
			}
			return *this;
		}

		WideString::ThisType& WideString::replace( int pos,int len,const Element* str,int size )
		{
			if(str && size>0 && pos>=0 && len>=0 && pos+len<=m_size)
			{
				ThisType temp;
				temp.expand(m_size-len+size);
				temp.append(m_string,pos);
				temp.append(str,size);
				temp.append(m_string+pos+len,m_size-pos-len);
				swap(temp);
			}
			return *this;
		}

		int WideString::find( Element c,int offset )const
		{
			if(m_string && m_size>0)
			{
				for (int i=offset;i<m_size;i++)
				{
					if(m_string[i]==c)
						return i;
				}
			}
			return npos;
		}

		int WideString::find( const Element* str,int offset )const
		{
			if(!m_string || m_size<=0)
				return npos;
			if(offset<0 || offset>=m_size)
				return npos;
			int len = str?length(str):0;
			if(len<=0)
				return npos;
			if(len+offset>m_size)
				return npos;
			int pos = SearchString(m_string+offset,m_size-offset,str,len,false);
			pos = pos>=0?(pos+offset):pos;
			return pos;
		}

		int WideString::rfind( Element c,int offset )const
		{
			if(m_string && m_size>0)
			{
				for (int i=m_size-1;i>=0;i--)
				{
					if(m_string[i]==c)
						return i;
				}
			}
			return npos;
		}

		void WideString::substr( int offset,int len,WideString::ThisType& bs )const
		{
			bs.clear();
			if(m_string && m_size>0 && len>0)
			{
				int pos = offset<0?0:offset;
				int size= (pos+len)>m_size?(m_size-pos):len;
				bs.append(m_string+pos,size);
			}
		}

		WideString::ThisType WideString::substr(int offset,int len)const
		{
			ThisType bs;
			substr(offset,len,bs);
			return bs;
		}

		int WideString::compare( const Element* str,int len ) const
		{
			if(!str || len<=0)
				return size()<=0?0:1;	// 有值为大
			if(size()<=0)
				return (!str||len<=0)?0:-1;

			// 字典排序
			int cmp = len<size()?len:size();
			int ret = wmemcmp(m_string, str, cmp);
			if(ret==0)
				return len==size()?0:(cmp==len?1:-1);
			return ret;
		}

		void WideString::swap( WideString& bs )
		{
			Element* tempstr = bs.m_string;
			int tempsize = bs.m_size;
			int tempcap  = bs.m_capcity;

			bs.m_string = m_string;
			bs.m_size	= m_size;
			bs.m_capcity= m_capcity;

			m_string	= tempstr;
			m_size		= tempsize;
			m_capcity	= tempcap;
		}

		qb::base::WideString::Element WideString::at( int i ) const
		{
			return m_string[i];
		}

		WideString::Element& WideString::at( int i )
		{
			return m_string[i];
		}

		////////////////////////////////////////////////////////////////////////////////
		int WideString::SearchString(const Element *mainStr,int mainStrLen,const Element *subStr,int subStrLen,bool ic)
		{
			mainStrLen*=2;
			subStrLen*=2;
			int pos = BaseString::SearchString((const char*)mainStr,mainStrLen*2,(const char*)subStr,subStrLen*2,ic);
			return pos>=0?pos/2:pos;
		}

		WideString& operator+=(WideString& bs,const WideString::Element* str)
		{
			return bs.append(str);
		}
		WideString& operator+=(WideString& bs,const WideString& plus)
		{
			return bs.append(plus);
		}
		bool operator<(const WideString& left,const WideString& right)
		{
			return left.compare(right.c_str(),right.size())<0;
		}

	}
}
